package com.zy.explore.demo.infrastructure.utils;

import com.google.common.collect.Lists;
import com.zy.explore.demo.infrastructure.exception.DefinitionException;
import com.wenwo.cloud.biz.domain.data.infrastructure.enums.ErrorCodeEnum;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.SimpleTimeZone;

/**
 * <p>Title: DateUtil</p>
 * <p>Description: </p>
 * <p>Company: </p>
 *
 * @author ZY
 * <p> Just go on !!!</p>
 * @date 2020年01月19日  15:46
 */
public class DateUtil {

    /**
     * yyyy/MM/dd格式
     */
    public static final String SHORT_PATTERN_1 = "yyyy/MM/dd";

    /**
     * yyyy-MM-dd格式
     */
    public static final String SHORT_PATTERN_2 = "yyyy-MM-dd";

    /**
     * yyyy.MM.dd格式
     */
    public static final String SHORT_PATTERN_3 = "yyyy.MM.dd";

    /**
     * yy_MM_dd格式
     */
    public static final String SHORT_PATTERN_4 = "yy_MM_dd";

    /**
     * yyyy/MM/dd HH:mm:ss格式
     */
    public static final String NORMAL_PATTERN_1 = "yyyy/MM/dd HH:mm:ss";

    /**
     * yyyy-MM-dd HH:mm:ss 格式
     */
    public static final String NORMAL_PATTERN_2 = "yyyy-MM-dd HH:mm:ss";

    /**
     * yyyy.MM.dd HH:mm:ss 格式
     */
    public static final String NORMAL_PATTERN_3 = "yyyy.MM.dd HH:mm:ss";

    /**
     * 获取昨天的日期
     *
     * @return
     */
    public static Date getYesterdayDate() {
        return getDate(-1);
    }

    /**
     * 获取距离当前日期前/后 n 天的日期
     *
     * @param n 传正数表示n天后，传负数表示n天前
     * @return
     */
    public static Date getDate(int n) {
        //计算昨天的日期
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        cal.add(Calendar.DATE, n);
        Date yestDate = cal.getTime();
        return yestDate;
    }

    /**
     * 获取距离给定日期前/后 n 天的日期
     *
     * @param n 传正数表示n天后，传负数表示n天前
     * @return
     */
    public static Date getDate(Date date, int n) {
        //计算昨天的日期
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, n);
        return cal.getTime();
    }

    /**
     * 获取距离给定日期前/后 n 天的格式化日期串
     *
     * @param date
     * @param n
     * @param pattern
     * @return
     */
    public static String getFormatDate(Date date, int n, String pattern) {
        return formatDate(getDate(date, n), pattern);
    }

    /**
     * 计算两个日期间一共有多少天(包括起始时间，即算头也算尾)
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int calcBetweenDays(Date date1, Date date2) {
        Long betweenDays = (date1.getTime() - date2.getTime()) / (1000 * 3600 * 24);
        return Math.abs(betweenDays.intValue());
    }

    /**
     * 格式化日期
     *
     * @param date
     * @param pattern
     * @return
     */
    public static String formatDate(Date date, String pattern) {
        return new SimpleDateFormat(pattern).format(date);
    }

    /**
     * 将日期字符串按给定格式解析为日期
     *
     * @param dateStr
     * @param pattern
     * @return
     * @throws Exception
     */
    public static Date parseDate(String dateStr, String pattern) throws Exception {
        return new SimpleDateFormat(pattern).parse(dateStr);
    }

    /**
     * 秒钟转换成这种格式的时间00:00:10
     *
     * @param time
     * @return
     */
    public static String secToTime(int time) {
        String timeStr;
        int hour = time / 3600;
        int minute = time / 60 % 60;
        int second = time % 60;
        timeStr = unitFormat(hour) + ":" + unitFormat(minute) + ":" + unitFormat(second);
        return timeStr;
    }

    /**
     * 格式化
     *
     * @param i
     * @return
     */
    public static String unitFormat(int i) {
        String retStr;
        int flag = 10;
        if (i >= 0 && i < flag) {
            retStr = "0" + i;
        } else {
            retStr = "" + i;
        }
        return retStr;
    }

    /**
     * 00:00:10 这种格式的时间转化成秒钟
     *
     * @param time
     * @return
     */
    public static int timeToSec(String time) {
        String[] timeArray = time.split(":");
        int hour = Integer.parseInt(timeArray[0]) * 3600;
        int min = Integer.parseInt(timeArray[1]) * 60;
        int sec = Integer.parseInt(timeArray[2]);
        return hour + min + sec;
    }


    /**
     * 根据前端参数获取对应的日期集合
     *
     * @param dateType  1.今天 2.昨天 3.最近7天 4.最近30天 5.自定义范围
     * @param dateRange 类型为5时，必传
     * @param max       最大间隔天数
     * @return
     * @throws Exception
     */
    public static List<String> getDateList(Integer dateType, String dateRange, Integer max) throws Exception {

        List<String> dateList = Lists.newArrayList();

        Date date;
        switch (dateType) {
            // 默认返回 今天
            default:
                date = DateUtil.getDate(0);
                dateList.add(DateUtil.formatDate(date, DateUtil.SHORT_PATTERN_2));
                break;
            // 昨天
            case 2:
                date = DateUtil.getDate(-1);
                dateList.add(DateUtil.formatDate(date, DateUtil.SHORT_PATTERN_2));
                break;

            // 最近7天
            case 3:
                int n = 6;
                for (int i = n; i >= 0; i--) {
                    date = DateUtil.getDate(-i);
                    dateList.add(DateUtil.formatDate(date, DateUtil.SHORT_PATTERN_2));
                }
                break;

            // 最近30天
            case 4:
                int m = 29;
                for (int i = m; i >= 0; i--) {
                    date = DateUtil.getDate(-i);
                    dateList.add(DateUtil.formatDate(date, DateUtil.SHORT_PATTERN_2));
                }
                break;

            // 选择时间段
            case 5:
                String[] dateRangeArr = dateRange.split("~");
                Date startDate;
                Date endDate;
                // 只支持 yyyy/MM/dd~yyyy/MM/dd 和 yyyy-MM-dd~yyyy-MM-dd 格式的时间范围
                String flag = "/";
                if (dateRangeArr[0].contains(flag)) {
                    startDate = DateUtil.parseDate(dateRangeArr[0], DateUtil.SHORT_PATTERN_1);
                    endDate = DateUtil.parseDate(dateRangeArr[1], DateUtil.SHORT_PATTERN_1);
                } else {
                    startDate = DateUtil.parseDate(dateRangeArr[0], DateUtil.SHORT_PATTERN_2);
                    endDate = DateUtil.parseDate(dateRangeArr[1], DateUtil.SHORT_PATTERN_2);
                }

                // 检验手动输入的两个日期差值是否超过90天
                int betweenDays = DateUtil.calcBetweenDays(startDate, endDate);
                if (betweenDays > max || betweenDays < 0) {
                    throw new DefinitionException(ErrorCodeEnum.DATE_OUT_OF_RANGE.getErrorCode(),
                            ErrorCodeEnum.DATE_OUT_OF_RANGE.getErrorMsg());
                }
                for (int i = betweenDays; i >= 0; i--) {
                    date = DateUtil.getDate(endDate, -i);
                    dateList.add(DateUtil.formatDate(date, DateUtil.SHORT_PATTERN_2));
                }
                break;
        }
        return dateList;
    }

    /**
     * 获取24小时集合
     * @return 返回24小时集合
     */
    public static List<String> getHoursList() {
        List<String> hours = Lists.newArrayList();
        int n = 24;
        for (int i = 0; i < n; i++) {
            if (i < 10) {
                hours.add("0" + i + ":00:00");
            } else {
                hours.add(i + ":00:00");
            }
        }
        return hours;
    }

    /**
     * mongo 日期查询isodate
     *
     * @param dateStr
     * @return
     */
    public static Date dateToIsoDate(String dateStr) {
        //T代表后面跟着时间，Z代表UTC统一时间
        Date date = formatD(dateStr);
        SimpleDateFormat format =
                new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        format.setCalendar(new GregorianCalendar(new SimpleTimeZone(0, "GMT")));
        String isoDate = format.format(date);
        try {
            return format.parse(isoDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Date formatD(String dateStr) {
        return formatD(dateStr, NORMAL_PATTERN_2);
    }

    public static Date formatD(String dateStr, String format) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        Date ret = null;
        try {
            ret = simpleDateFormat.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return ret;
    }

    /**
     * 根据出生年月计算年龄
     *
     * @param birthday 出生年月
     * @return 返回年龄
     */
    public static int getAgeFromBirth(String birthday) {
        // 先截取到字符串中的年、月、日
        String[] strs = birthday.trim().split("-");
        int selectYear = Integer.parseInt(strs[0]);
        int selectMonth = Integer.parseInt(strs[1]);
        int selectDay = Integer.parseInt(strs[2]);
        // 得到当前时间的年、月、日
        Calendar cal = Calendar.getInstance();
        int yearNow = cal.get(Calendar.YEAR);
        int monthNow = cal.get(Calendar.MONTH) + 1;
        int dayNow = cal.get(Calendar.DATE);

        // 用当前年月日减去生日年月日
        int yearMinus = yearNow - selectYear;
        int monthMinus = monthNow - selectMonth;
        int dayMinus = dayNow - selectDay;

        // 先大致赋值
        int age = yearMinus;
        // 选了未来的年份
        if (yearMinus < 0) {
            age = 0;
            // 同年的，要么为1，要么为0
        } else if (yearMinus == 0) {
            if (monthMinus < 0) {
                // 选了未来的月份
                // 同月份的
            } else if (monthMinus == 0) {
                // 选了未来的日期
                if (dayMinus < 0) {
                    age = 0;
                } else {
                    age = 1;
                }
            } else {
                age = 1;
            }
        } else {
            // 当前月>生日月
            if (monthMinus < 0) {
                // 同月份的，再根据日期计算年龄
            } else if (monthMinus == 0) {
                if (dayMinus < 0) {
                } else {
                    age = age + 1;
                }
            } else {
                age = age + 1;
            }
        }
        return age;
    }

}
